package infra_domainservice

import (
	"lzq-admin/base/domainservice"
	infra_model "lzq-admin/internal/infrastructure/model"
	token "lzq-admin/pkg/auth"
	"lzq-admin/pkg/orm"
	"lzq-admin/pkg/utility"
	"strings"
	"sync"

	"github.com/ahmetb/go-linq/v3"
	"github.com/gin-gonic/gin"
	"xorm.io/xorm"
)

/**
 * @Author  糊涂的老知青
 * @Date    2021/12/6
 * @Version 1.0.0
 */

type AuthRolePermissionDomainService struct {
	domainservice.BaseDomainService
	wg sync.WaitGroup
}

func NewDSAuthRolePermission(c *gin.Context) *AuthRolePermissionDomainService {
	return &AuthRolePermissionDomainService{
		domainservice.BaseDomainService{
			GinCtx: c,
		},
		sync.WaitGroup{},
	}
}

func (s *AuthRolePermissionDomainService) Insert(modelDtoes []infra_model.CreateAuthRolePermissionDto) ([]infra_model.AuthRolePermission, error) {
	var iEntities []infra_model.AuthRolePermission
	var uEntities []infra_model.AuthRolePermission
	var err error
	var rolePermissionList = make([]infra_model.AuthRolePermission, 0)
	roleIds := make([]string, 0)
	lzqOrm := orm.NewLzqOrm(s.GinCtx)
	linq.From(modelDtoes).SelectT(func(s infra_model.CreateAuthRolePermissionDto) string { return s.RoleId }).Distinct().ToSlice(&roleIds)
	if err = lzqOrm.QSession(true).Where("RoleId in(?)", strings.Join(roleIds, ",")).Find(&rolePermissionList); err != nil {
		return nil, err
	}
	for _, v := range modelDtoes {
		m := infra_model.AuthRolePermission{
			AuthRolePermissionBase: infra_model.AuthRolePermissionBase{
				RoleId:       v.RoleId,
				PermissionId: v.PermissionId,
				IsGranted:    v.IsGranted,
			},
		}
		firsts := make([]infra_model.AuthRolePermission, 0)
		linq.From(rolePermissionList).WhereT(func(w infra_model.AuthRolePermission) bool {
			return w.RoleId == v.RoleId && w.PermissionId == v.PermissionId
		}).ToSlice(&firsts)
		claims := token.GetClaims(s.GinCtx)
		if len(firsts) > 0 {
			first := firsts[0]
			first.IsGranted = m.IsGranted
			uEntities = append(uEntities, first)
		} else {
			m.ID = utility.UuidCreate()
			m.TenantId = claims.TenantId
			m.CreatorId = claims.Id
			iEntities = append(iEntities, m)
		}
	}
	var dbSession *xorm.Session
	// 开启事务
	if dbSession, err = lzqOrm.BeginTrans(); err != nil {
		dbSession.Rollback()
		return nil, err
	}
	s.wg.Add(1)
	go func() {
		if len(iEntities) > 0 {
			if _, err := dbSession.Insert(&iEntities); err != nil {
				dbSession.Rollback()
				s.wg.Done()
				return
			}
		}
		s.wg.Done()
	}()

	if len(uEntities) > 0 {
		for _, u := range uEntities {
			if _, err := lzqOrm.USessionWithTrans(true, dbSession).ID(u.ID).UseBool("IsGranted").Update(&u); err != nil {
				dbSession.Rollback()
				return nil, err
			}
		}
	}
	s.wg.Wait()
	iEntities = append(iEntities, uEntities...)

	if err := dbSession.Commit(); err != nil {
		dbSession.Rollback()
		return nil, err
	}
	return iEntities, err
}
